package mylittleinvestigations.GameUi;

import java.util.logging.Level;
import java.util.logging.Logger;
import mylittleinvestigations.CaseInformation.Case;
import mylittleinvestigations.EasingFunctions.EasingFunction;
import mylittleinvestigations.EasingFunctions.LinearEase;
import mylittleinvestigations.Events.ButtonEventProvider;
import mylittleinvestigations.MouseHelper;
import mylittleinvestigations.PersistentThreads.RenderThread;
import mylittleinvestigations.Settings;
import mylittleinvestigations.Sprite;
import mylittleinvestigations.Vector2;
import org.dawnmew.jpurewave.SoundSystem;
import org.newdawn.slick.*;
import org.newdawn.slick.geom.Rectangle;

public class Button
{
    private static final int AnimationDuration = 200;
    private static final int TextHeight = 29;

    private static final Color NormalTextColor = Color.white;
    private static final Color MouseOverTextColor = Color.yellow;
    private static final Color MouseDownTextColor = Color.red;
    private static final Color DisabledTextColor = Color.gray;

    private static UnicodeFont textFont;
    private static Image checkMarkTexture;
    private static Image lockTexture;

    private int id;
    private String customIconId;
    private Sprite customIconSprite;

    private boolean isMouseOver;
    private boolean isMouseDown;

    private EasingFunction inEase;
    private EasingFunction outEase;
    private int animationOffset;

    private String clickSoundEffect = "ButtonClick1";

    public static void Initialize(UnicodeFont textFont, Image checkMarkTexture, Image lockTexture)
    {
        try
        {
            textFont.loadGlyphs();
        }
        catch (SlickException ex)
        {
            Logger.getLogger(Button.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        Button.textFont = textFont;
        Button.checkMarkTexture = checkMarkTexture;
        Button.lockTexture = lockTexture;
    }

    public Button(int id, String text)
    {
        this.id = id;
        this.text = text;
        this.showCheckMark = false;
        this.isDisabled = false;

        this.inEase = new LinearEase(Settings.DisplayBounds.getX(), 0, AnimationDuration);
        this.outEase = new LinearEase(0, -Settings.DisplayBounds.getX(), AnimationDuration);

        this.Reset();
    }
    
    public int getId() { return this.id; }

    private int xPosition;

    public int getXPosition() { return this.xPosition; }
    public void setXPosition(int xPosition) { this.xPosition = xPosition; }

    private int yPosition;

    public int getYPosition() { return this.yPosition; }
    public void setYPosition(int yPosition) { this.yPosition = yPosition; }

    public String getClickSoundEffect()
    {
        return this.clickSoundEffect;
    }

    public String getCustomIconId()
    {
        return this.customIconId;
    }
    
    public void setCustomIconId(String customIconId)
    {
        this.customIconId = customIconId;

        if (this.customIconId != null)
        {
            this.customIconSprite = Case.getInstance().getSpriteManager().GetSpriteFromId(this.customIconId);
        }
        else
        {
            this.customIconSprite = null;
        }
    }

    private boolean isHidden;

    public boolean getIsHidden() { return this.isHidden; }
    public void setIsHidden(boolean isHidden) { this.isHidden = isHidden; }

    private boolean isHiding;

    public boolean getIsHiding() { return this.isHiding; }
    public void setIsHiding(boolean isHiding) { this.isHiding = isHiding; }

    private String text;

    public String getText() { return this.text; }
    private void setText(String text) { this.text = text; }

    public int getInAnimationDelay()
    {
        return this.inEase.getAnimationStartDelay();
    }

    public void setInAnimationDelay(int value)
    {
        this.inEase.setAnimationStartDelay(value);
    }

    public int getOutAnimationDelay()
    {
        return this.outEase.getAnimationStartDelay();
    }

    public void setOutAnimationDelay(int value)
    {
        this.outEase.setAnimationStartDelay(value);
    }

    private boolean showCheckMark;

    public boolean getShowCheckMark() { return this.showCheckMark; }
    public void setShowCheckMark(boolean showCheckMark) { this.showCheckMark = showCheckMark; }

    private boolean LockQuestionMark;

    public boolean getShowLock() { return this.LockQuestionMark; }
    public void setShowLock(boolean showLock) { this.LockQuestionMark = showLock; }

    private boolean isDisabled;

    public boolean getIsDisabled() { return this.isDisabled; }
    public void setIsDisabled(boolean isDisabled) { this.isDisabled = isDisabled; }

    public boolean getIsReady()
    {
        return this.inEase.getIsFinished() && !this.outEase.getIsStarted();
    }

    public void Show()
    {
        this.Reset();
        this.setIsHidden(false);
        this.inEase.Begin();
    }

    public void ShowInstantly()
    {
        this.Reset();
        this.setIsHidden(false);
        this.inEase.Finish();
        this.animationOffset = (int)this.inEase.GetCurrentValue();
    }

    public void Hide()
    {
        this.outEase.Begin();
    }

    public void Update(GameContainer gc,int delta)
    {
        this.isMouseOver = false;
        this.isMouseDown = false;

        if (this.outEase.getIsStarted() && !this.outEase.getIsFinished())
        {
            this.outEase.Update(gc,delta);
            this.animationOffset = (int)this.outEase.GetCurrentValue();
        }
        else if (this.outEase.getIsFinished())
        {
            this.setIsHidden(true);
        }
        else if (this.inEase.getIsStarted() && !this.inEase.getIsFinished())
        {
            this.inEase.Update(gc,delta);
            this.animationOffset = (int)this.inEase.GetCurrentValue();
        }
        else
        {
            if (!this.getIsDisabled())
            {
                Rectangle positionRect = new Rectangle(this.getXPosition(), this.getYPosition(), textFont.getWidth(this.getText()), TextHeight);

                if (MouseHelper.ClickedOnRect(positionRect))
                {
                    this.OnClicked();
                }

                if (MouseHelper.MouseDownOnRect(positionRect))
                {
                    this.isMouseDown = true;
                }
                else if (MouseHelper.MouseOverRect(positionRect))
                {
                    this.isMouseOver = true;
                }
            }
        }

        if (this.isMouseOver || this.isMouseDown)
        {
            MouseHelper.SetToHandCursor();
        }
    }

    public void Draw(GameContainer gc, Graphics g)
    {
        this.Draw(gc, g, 0);
    }

    public void Draw(GameContainer gc, Graphics g, float yOffset)
    {
        Color textColor;

        if (this.getIsDisabled())
        {
            textColor = DisabledTextColor;
        }
        else if (this.isMouseDown)
        {
            textColor = MouseDownTextColor;
        }
        else if (this.isMouseOver)
        {
            textColor = MouseOverTextColor;
        }
        else
        {
            textColor = NormalTextColor;
        }

        Vector2 textPosition = new Vector2(
                this.getXPosition() + this.animationOffset,
                this.getYPosition() + yOffset);

        RenderThread.getInstance().AddStringToRenderQueue(textFont, (float)textPosition.getX(), (float)textPosition.getY(), this.getText(), textColor);

        if (this.customIconSprite != null)
        {
            Vector2 spritePosition =
                new Vector2(
                    textPosition.getX() - this.customIconSprite.getWidth() - 4,
                    textPosition.getY() - 4 + (36 - this.customIconSprite.getHeight()) / 2);

            this.customIconSprite.Draw(gc, g, spritePosition);
        }
        else if (this.getShowLock())
        {
            Vector2 lockPosition =
                new Vector2(
                    textPosition.getX() - lockTexture.getWidth() - 2,
                    textPosition.getY() - 2);

            RenderThread.getInstance().AddImageToRenderQueue(lockTexture, (float)lockPosition.getX(), (float)lockPosition.getY());
        }
        else if (this.getShowCheckMark())
        {
            Vector2 checkMarkPosition =
                new Vector2(
                    textPosition.getX() - checkMarkTexture.getWidth(),
                    textPosition.getY() - 4);

            RenderThread.getInstance().AddImageToRenderQueue(checkMarkTexture, (float)checkMarkPosition.getX(), (float)checkMarkPosition.getY());
        }
    }

    public void Reset()
    {
        this.setIsHidden(true);
        this.animationOffset = (int)Settings.DisplayBounds.getX();
        this.inEase.Reset();
        this.outEase.Reset();
        this.isMouseOver = false;
        this.isMouseDown = false;
    }

    private void OnClicked()
    {
        ButtonEventProvider.RaiseClicked(this, this.id);
        SoundSystem.getInstance().playSound(getClickSoundEffect());
    }
}
